<?php

declare(strict_types=1);

namespace App\Repositories\Senior;


use App\Enums\SeniorEnum;
use App\Exceptions\BasicException;
use App\Models\GameDB\Pet\Props;
use App\Models\GameDB\Pet\PropsExchangeLog;
use App\Models\GameDB\Pet\PropsGiftConfig;
use App\Models\GameDB\Pet\UserPropsLog;
use App\Models\MainDB\Gift;
use App\Models\MainDB\UserData;
use App\Services\Draw\DrawObject\Senior;
use App\Traits\Singleton;
use Illuminate\Support\Facades\DB;

class SeniorGiftRepository
{
    use Singleton;


    public function getGiftList($param)
    {
        $offset     = ($param['page'] - 1) * $param['perPage'];
        $query      = PropsGiftConfig::query()->where('is_delete', 0);
        $totalCount = $query->count();
        $list       = $query->get()->toArray();
        $giftIds    = array_column($list, 'gift_id');
        $list       = array_column($list, null, 'gift_id');
        $result     = Gift::query()->whereIn('id', $giftIds)->select('id', 'name', 'picture', 'price')->orderBy('price', 'desc')->offset($offset)->limit($param['perPage'])
            ->get()->toArray();


//        $list = $query->orderBy('id', 'desc')->offset($offset)->limit($param['perPage'])->get()->toArray();
//        $giftIds = array_column($list, 'gift_id');
//        $giftInfos = $this->getGiftInfoByIds($giftIds);
        $propsIds  = array_column($list, 'props_id');
        $propInfos = SeniorPropsRepository::getInstance()->getPropInfoByIds($propsIds);
        $resList   = [];
        foreach ($result as $item) {
            $resItem               = $list[$item['id']];
            $resItem['gift_name']  = $item['name'] ?? '';
            $resItem['gift_icon']  = $item['picture'] ?? '';
            $resItem['gift_price'] = $item['price'] ?? 0;
            $resItem['game_name']  = $propInfos[$resItem['props_id']]['game_name'] ?? '';
            $resItem['props_icon'] = $propInfos[$resItem['props_id']]['prope_icon'] ?? '';
            $resItem['jump_info']  = $this->getJumpUrl($propInfos[$resItem['props_id']]['game']);
            $resList[]             = $resItem;
        }
        return ['total' => $totalCount, 'list' => $resList];
    }


    //根据礼物id获取礼物信息
    public function getGiftInfoByIds(array $giftIds)
    {
        $giftInfos = Gift::query()->whereIn('id', $giftIds)->select('id', 'name', 'picture', 'price')
            ->get()->toArray();
        return array_column($giftInfos, null, 'id');
    }


    /**
     * 兑换礼物
     *
     * @param     $configId
     * @param int $num
     */
    public function exchange($configId, $count = 1)
    {
        $key = SeniorEnum::USER_GIFT_EXCHANGE_LOCK . UID;
        try {
            $res = app("redis")->set($key, time(), 'ex', 5, 'nx');
            if (!$res) {
                throw new BasicException(-1, "操作太频繁，请稍后再试");
            }
            $configInfo = PropsGiftConfig::query()->find($configId);
            if (empty($configInfo)) {
                throw new BasicException(-1, "不存在的兑换信息，请选择正确的礼物兑换");
            }
            $propsInfo = Props::query()->find($configInfo->props_id);
            $check     = $this->checkExchange(UID, $configInfo, $count);
            if (!$check) {
                throw new BasicException(-1, "道具数量不足,再去试试手气吧");
            }
            //开始兑换
            DB::beginTransaction();
            $startExchange = 1;
            $userData      = UserData::query()->where('user_id', UID)->first();
            //增加兑换记录
            PropsExchangeLog::query()->create([
                'nickname'    => $userData->nickname ?? '',
                'user_code'   => $userData->user_code ?? 0,
                'user_id'     => $userData->user_id ?? 0,
                'props_id'    => $configInfo->props_id,
                'props_count' => $configInfo->props_count,
                'gift_id'     => $configInfo['gift_id'],
                'game'        => $propsInfo->game,
            ]);
            //扣除用户道具
            $descPropCount = $count * $configInfo->props_count;
            $this->descProps($userData->user_id, $configInfo->props_id, $descPropCount);
            //todo 给用户增加礼物
            $this->addUserGift($userData->user_id, $configInfo['gift_id']);
            DB::commit();
            //结束兑换
            return $this->getJumpUrl($propsInfo->game);
        } catch (\Exception $exception) {
            if (isset($startExchange)) {
                DB::rollBack();
            }
            throw new BasicException(-1, $exception->getMessage());
        } finally {
            app("redis")->del($key);
        }
    }

    public function getJumpUrl($game)
    {
        return SeniorEnum::PROPS_GAME_URL[$game] ?? ['android' => '', 'ios' => ''];
    }


    /**
     * 扣除用户道具
     *
     * @param $userId
     * @param $props_id
     * @param $count
     */
    public function descProps($userId, $propsId, $count)
    {
        //todo 扣除用户道具
        $userProps = UserPropsLog::query()->where(['user_id' => $userId, 'props_id' => $propsId])
            ->where('effective_at', '>', time())->where('un_used_num', '>', 0)->orderBy('effective_at', 'asc')
            ->get();
        foreach ($userProps as $prop) {
            $update = [];
            if ($prop->un_used_num >= $count) {
                $update['used_num']    = $prop->used_num + $count;
                $update['un_used_num'] = $prop->un_used_num - $count;
                $count                 = 0;
            } else {
                $count                 = $count - $prop->un_used_num;
                $update['used_num']    = $prop->props_num;
                $update['un_used_num'] = 0;
                $update['is_used']     = 1;
            }
            UserPropsLog::query()->where('id', $prop->id)->update($update);
            if ($count == 0) {
                return;
            }
        }
    }

    /**
     * 给用户增加礼物
     *
     * @param $userId
     * @param $gift_id
     */
    public function addUserGift($userId, $gift_id)
    {
        app('model_gift_backpack')->sendBackpackGift($userId, $gift_id, 1);
    }


    /**
     * 校验兑换条件
     *
     * @param $userId
     * @param $config
     * @param $count
     */
    public function checkExchange($userId, $config, $count)
    {
        $propCount = UserPropsLog::query()->where(['user_id' => $userId, 'props_id' => $config->props_id])
            ->where('effective_at', '>', time())->sum('un_used_num');
        $needCount = $count * $config->props_count;
        if ($propCount >= $needCount) {
            return true;
        }
        return false;
    }

    /**
     * 获取播报列表
     */
    public function getLogList()
    {
        $list      = PropsExchangeLog::query()->orderBy('id', 'desc')->limit(20)->get()->toArray();
        $giftIds   = array_column($list, 'gift_id');
        $userIds   = array_column($list, 'user_id');
        $gifts     = $this->getGiftInfoByIds($giftIds);
        $userNames = UserData::query()->whereIn('user_id', $userIds)->select('user_id', 'nickname')->get()->keyBy('user_id')->toArray();
        $res       = [];
        foreach ($list as &$item) {
            $res[] = [
                'gift_name'  => $gifts[$item['gift_id']]['name'] ?? '',
                'gift_price' => $gifts[$item['gift_id']]['price'] ?? 0,
                'user_name'  => $userNames[$item['user_id']]['nickname'] ?? '',
            ];
        }
        return $res;
    }

    public function getUnUsedProps()
    {
        $propIds   = UserPropsLog::query()->where('user_id', UID)->groupBy(['props_id'])->pluck('props_id')->toArray();
        $propInfos = Props::query()->whereIn('id', $propIds)->select('id', 'name', 'prope_icon', 'effective_icon')->get()->toArray();


        foreach ($propInfos as &$item) {
            $query                        = UserPropsLog::query()->where(['user_id' => UID, 'props_id' => $item['id']]);
            $weekEffectiveProps           = (clone $query)->where('effective_at', '>', time())->where('effective_at', '<', strtotime("+3 days"))->sum('un_used_num');
            $totalProps                   = $query->where('effective_at', '>', time())->sum('un_used_num');
            $item['total_props']          = $totalProps;
            $item['week_effective_props'] = $weekEffectiveProps;
        }
        return $propInfos ?? [];
    }
}
